#ifndef PROTOCAL_HPP // 若未定义过 PROTOCAL_HPP
#define PROTOCAL_HPP // 定义 PROTOCAL_HPP

#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>
// #define MySelf 0
using namespace std;

const string blank_space_sep = " ";
const string protocal_sep = "\n";

// 为有效载荷添加报头："len""\n""x op y""\n"
string encode(string &content)
{
    string package = to_string(content.size());
    package += protocal_sep;
    package += content;
    package += protocal_sep;
    return package;
}

// 从报文中解析出有效载荷
bool decode(string &package, string *content)
{
    size_t pos = package.find(protocal_sep);
    if (pos == string::npos)
        return false;
    string len_str = package.substr(0, pos);
    size_t len = stoi(len_str);
    size_t total_len = len_str.size() + len + 2;
    if (total_len > package.size())
        return false;
    *content = package.substr(pos + 1, len);
    package.erase(0, total_len); // 为了处理下一条报文，content提取到一条完整的报文后就将它从package移除

    return true;
}

// 封装「客户端请求」数据
class Request
{
public:
    Request(int data1, int data2, char oper)
        : x(data1), y(data2), op(oper)
    {
    }

    Request() {}

public:
    // 序列化 —— 对象转字符串
    // 将 Request 对象（包含 x、op、y）序列化为字符串 "x op y" 格式
    bool serialize(string *out)
    {
#ifdef MySelf
        // 一条报文的格式："len""\n""x op y"

        // 构建报文的有效载荷
        //  struct => string, "x op y"
        string s = to_string(x);
        s += blank_space_sep;
        s += op;
        s += blank_space_sep;
        s += to_string(y);

        *out = s;

        return true;
#else
        Json::Value root;
        root["x"] = x;
        root["y"] = y;
        root["op"] = op;

        // 序列化
        // Json::FastWriter w;
        Json::StyledWriter w;
        *out = w.write(root); // 用紧凑格式生成JSON字符串
        return true;
#endif
    }

    // 反序列化 —— 字符串转对象
    // 从字符串解析出数据并赋值给 Request 对象（x、y、op）
    bool deserialize(const string &in)
    {
#ifdef MySelf
        size_t left = in.find(blank_space_sep);
        if (left == string::npos)
            return false;
        string part_x = in.substr(0, left);

        size_t right = in.rfind(blank_space_sep);
        if (right == string::npos)
            return false;
        string part_y = in.substr(right + 1);

        if (left + 2 != right)
            return false;
        op = in[left + 1];
        x = stoi(part_x);
        y = stoi(part_y);

        return true;
#else
        Json::Value root;
        Json::Reader r;
        r.parse(in, root);

        x = root["x"].asInt();
        y = root["y"].asInt();
        op = root["op"].asInt();
        return true;
#endif
    }

    void debugPrint()
    {
        cout << "新请求构建完成：" << x << op << y << "=?" << endl;
    }

public:
    int x;
    int y;
    char op; // + - * / %
};

// 封装「服务器响应」数据
class Response
{
public:
    Response(int res, int code)
        : _result(res), _code(0)
    {
    }

    Response() {}

public:
    bool serialize(string *out)
    {
#ifdef MySelf
        // 一条报文的格式："len""\n""result code"

        // 构建报文的有效载荷
        string s = to_string(_result);
        s += blank_space_sep;
        s += to_string(_code);

        *out = s;

        return true;
#else
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;

        // 序列化
        // Json::FastWriter w;
        Json::StyledWriter w;
        *out = w.write(root); // 用紧凑格式生成JSON字符串
        return true;
#endif
    }

    bool deserialize(const string &in)
    {
#ifdef MySelf
        size_t pos = in.find(blank_space_sep);
        if (pos == string::npos)
            return false;
        string part_res = in.substr(0, pos);
        string part_code = in.substr(pos + 1);

        _result = stoi(part_res);
        _code = stoi(part_code);

        return true;
#else
        Json::Value root;
        Json::Reader r;
        r.parse(in, root);

        _result = root["result"].asInt();
        _code = root["code"].asInt();
        return true;
#endif
    }

    void debugPrint()
    {
        cout << "结果响应完成, result:" << _result << " code:" << _code << endl;
    }

public:
    int _result;
    int _code; // 0-可信 !0-不可信，具体是积，表明错误原因
};

#endif // 结束保护，若已定义过 PROTOCAL_HPP，则跳过中间内容